#include <iostream>
#include <chrono>
#include <thread>
#include <windows.h>
#include <pdh.h>
#include <pdhmsg.h>
#include <string>
#include <vector>
#include <sstream>
#include <iomanip> // 新增：用于 std::fixed 和 std::setprecision
#include <locale>  // 新增：与 cpu_usage_50.cpp 保持一致

#pragma comment(lib, "pdh.lib")

class CPUCoreMonitor {
private:
    PDH_HQUERY query;
    PDH_HCOUNTER counter;
    int coreIndex;
    
public:
    CPUCoreMonitor(int core) : coreIndex(core) {
        // 初始化PDH查询
        PdhOpenQueryW(nullptr, 0, &query); // 使用 PdhOpenQueryW 保持一致性
        
        // 构建特定核心的计数器路径
        std::wstringstream counterPath;
        counterPath << L"\\Processor(" << coreIndex << L")\\% Processor Time";
        
        // 添加特定核心的CPU使用率计数器
        PDH_STATUS status = PdhAddCounterW(query, counterPath.str().c_str(), 0, &counter);
        if (status != ERROR_SUCCESS) {
            std::wcerr << L"Error adding counter: " << counterPath.str() << L" Error code: 0x" << std::hex << status << std::endl;
            // 可以选择抛出异常或设置错误状态
        }
        // 首次收集数据（初始化计数器）
        status = PdhCollectQueryData(query);
        if (status != ERROR_SUCCESS) {
            std::cerr << "\nError in PdhCollectQueryData (constructor): 0x" << std::hex << status << std::endl;
        }
    }

    ~CPUCoreMonitor() {
        // 清理资源
        PdhCloseQuery(query);
    }

    // 获取特定核心的CPU使用率（百分比）
    double getCPUCoreUsage() {
        PDH_FMT_COUNTERVALUE counterVal;
        PDH_STATUS status;
        
        // 收集新数据
        status = PdhCollectQueryData(query);
        if (status != ERROR_SUCCESS) {
            // 不换行，以便与\r配合使用
            std::cerr << " Error PdhCollectQueryData: 0x" << std::hex << status << " ";
            return -1.0; // 指示错误
        }
        
        // 获取格式化的计数器值
        status = PdhGetFormattedCounterValue(counter, PDH_FMT_DOUBLE, nullptr, &counterVal);
        if (status != ERROR_SUCCESS) {
            // 不换行
            std::cerr << " Error PdhGetFormattedCounterValue: 0x" << std::hex << status << " ";
            // PDH_INVALID_DATA (0xC0000BC6) 是一个常见的“错误”，如果 PdhCollectQueryData 只被调用了一次
            // 但在我们的设计中，构造函数调用一次，此函数每次调用也会调用，所以第二次调用此函数后应该有效
            return -1.0; // 指示错误
        }
        
        return counterVal.doubleValue;
    }
};

// 获取系统逻辑处理器数量
int getProcessorCount() {
    SYSTEM_INFO sysInfo;
    GetSystemInfo(&sysInfo);
    return sysInfo.dwNumberOfProcessors;
}

// 执行工作负载的函数，可以通过调整睡眠时间来控制特定CPU核心的使用率
void performCoreWorkload(int coreIndex, double targetUsage, int intervalMs) {
    // 创建一个针对特定核心的CPU使用率监视器
    CPUCoreMonitor monitor(coreIndex);
    
    // 初始工作/睡眠比例
    int workTimeMs = intervalMs / 2;
    int sleepTimeMs = intervalMs - workTimeMs; // sleepTimeMs will be recalculated in the loop
    
    // 设置线程亲和性，确保线程在指定的核心上运行
    HANDLE currentThread = GetCurrentThread();
    DWORD_PTR mask = (static_cast<DWORD_PTR>(1) << coreIndex);
    SetThreadAffinityMask(currentThread, mask);
    
    // 校准：基于一个参考点调整内部PDH目标。
    // 例如：如果当程序以PDH读数50%为目标时，观察到实际CPU使用率为75%，
    // 那么 K = PDH_参考值 / 实际CPU_参考值 = 50.0 / 75.0 approx 0.667.
    // 内部PDH目标 = 用户请求的实际目标使用率 * K.
    // 注意：这种线性校准是一个近似值，其准确性可能随目标CPU使用率的不同而变化。
    const double CALIBRATION_REFERENCE_PDH_TARGET = 50.0;
    const double CALIBRATION_REFERENCE_ACTUAL_USAGE = 75.0; // 基于观察：目标50%时，实际70-80%
    
    double scalingFactor = 1.0; // 默认无缩放
    if (CALIBRATION_REFERENCE_ACTUAL_USAGE > 0.0) { // 防止除以零
        scalingFactor = CALIBRATION_REFERENCE_PDH_TARGET / CALIBRATION_REFERENCE_ACTUAL_USAGE;
    }
    
    double internalPdhTarget = targetUsage * scalingFactor;

    // 确保 internalPdhTarget 处于PDH计数器的有效范围内 [0, 100]。
    // 由于 targetUsage <= 100 和 scalingFactor < 1 (通常情况下), internalPdhTarget 通常远小于100。
    internalPdhTarget = std::max(0.0, std::min(internalPdhTarget, 100.0));


    std::cout << "开始控制CPU核心 " << coreIndex << " 的使用率在 " << targetUsage << "% 左右..." << std::endl;
    std::cout << "(校准后内部PDH目标: " << internalPdhTarget << "%, 使用缩放因子: " << scalingFactor << ")" << std::endl;
    std::cout << "按Ctrl+C退出程序" << std::endl;
    
    bool first_reading = true;
    while (true) {
        // 获取当前核心的CPU使用率
        double currentUsage = monitor.getCPUCoreUsage();

        if (first_reading && currentUsage == 0.0) {
            // PDH计数器第一次读取格式化值可能为0，直到收集到两个样本点。
            // 给它一个循环来获取第二个样本点。
            std::cout << "\r核心 " << coreIndex << " 正在初始化使用率读数...          " << std::flush;
            std::this_thread::sleep_for(std::chrono::milliseconds(intervalMs)); // 等待一个周期
            first_reading = false;
            continue;
        }
        first_reading = false;

        if (currentUsage < 0.0) { // 表示 getCPUCoreUsage 内部发生错误
            std::cout << "\r核心 " << coreIndex << " 获取使用率失败. 跳过调整.     " << std::flush;
            // 发生错误时，可以选择暂停一下或使用默认工作/休眠时间
            std::this_thread::sleep_for(std::chrono::milliseconds(intervalMs));
            continue; 
        }
        
        // 定义调整步长，例如周期的2%，但至少为1ms
        int adjustment_step = std::max(1, intervalMs / 50);

        // 根据当前使用率调整工作/睡眠时间比例 (与校准后的 internalPdhTarget 比较)
        if (currentUsage < internalPdhTarget - 2.0) { 
            workTimeMs += adjustment_step;
        } else if (currentUsage > internalPdhTarget + 2.0) { 
            workTimeMs -= adjustment_step;
        }
        
        // 确保工作和睡眠时间在合理范围内
        workTimeMs = std::max(0, std::min(workTimeMs, intervalMs));
        sleepTimeMs = intervalMs - workTimeMs; // 在调整并限制 workTimeMs 后重新计算 sleepTimeMs
        
        // 打印当前CPU使用率和调整后的时间
        std::cout << "\r核心 " << coreIndex << " 的使用率: " << currentUsage 
                  << "%, 工作时间: " << workTimeMs << "ms, 睡眠时间: " 
                  << sleepTimeMs << "ms     " << std::flush;
        
        // 执行计算密集型工作
        auto start = std::chrono::high_resolution_clock::now();
        while (std::chrono::duration_cast<std::chrono::milliseconds>(
               std::chrono::high_resolution_clock::now() - start).count() < workTimeMs) {
            // 空循环，消耗CPU
            volatile double dummy = 0;
            for (int i = 0; i < 10000; ++i) {
                dummy = dummy + i * 1.1;
            }
        }
        
        // 休眠一段时间
        if (sleepTimeMs > 0) {
            std::this_thread::sleep_for(std::chrono::milliseconds(sleepTimeMs));
        }
    }
}

int main(int argc, char* argv[]) {
    // 设置控制台输出为UTF-8以正确显示中文
    if (!SetConsoleOutputCP(CP_UTF8)) {
        // 如果设置失败，输出错误信息到标准错误流
        // 注意：此时 std::cerr 可能也无法正确显示中文错误信息，但错误码可以帮助诊断
        DWORD error = GetLastError();
        char errBuf[256];
        sprintf_s(errBuf, sizeof(errBuf), "Warning: Failed to set console output to UTF-8. Error code: %lu\n", error);
        WriteConsoleA(GetStdHandle(STD_ERROR_HANDLE), errBuf, strlen(errBuf), NULL, NULL);
    }
    
    // 为double设置输出格式，与cpu_usage_50.cpp保持一致
    std::cout << std::fixed << std::setprecision(2); 
    
    // 默认值
    int coreIndex = 0;
    double targetUsage = 50.0;
    int intervalMs = 500; // 将默认控制周期从 100ms 增加到 500ms
    
    // 解析命令行参数
    if (argc >= 2) {
        try {
            coreIndex = std::stoi(argv[1]);
        } catch (const std::exception& e) {
            std::cerr << "无效的核心索引: " << argv[1] << std::endl;
            return 1;
        }
    }
    
    if (argc >= 3) {
        try {
            targetUsage = std::stod(argv[2]);
            if (targetUsage < 0 || targetUsage > 100) {
                std::cerr << "目标使用率必须在0到100之间" << std::endl;
                return 1;
            }
        } catch (const std::exception& e) {
            std::cerr << "无效的目标使用率: " << argv[2] << std::endl;
            return 1;
        }
    }
    
    // 检查核心索引是否有效
    int processorCount = getProcessorCount();
    if (coreIndex < 0 || coreIndex >= processorCount) {
        std::cerr << "错误: 核心索引超出范围 (0-" << (processorCount - 1) << ")" << std::endl;
        return 1;
    }
    
    std::cout << "系统共有 " << processorCount << " 个逻辑处理器" << std::endl;
    
    // 执行核心工作负载控制
    performCoreWorkload(coreIndex, targetUsage, intervalMs);
    
    return 0;
}
